package net.suntec.mrs.client.message;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

import net.suntec.mrs.client.common.Utils;

public abstract class MessageSender {

	/** Type字节数 */
	private final static int TYPE_SIZE = 1;
	/** 内容长度字节数 */
	private final static int CONTENT_LEN_SIZE = 3;
	/** 令牌字节数 */
	private final static int TOKEN_SIZE = 32;

	protected String userToken;
	protected String host;
	protected int port;

	public MessageSender( String userToken, final String host, final int port ) {
		this.userToken = userToken;
		this.host = host;
		this.port = port;
	}

	protected abstract byte[] prepareContent() throws IOException;

	protected abstract void processResponse( byte[] reps );

	public void send() throws IOException {
		int content_len = 0;

		// 获取消息内容
		byte[] content_bytes = prepareContent();
		if ( content_bytes == null || ( content_len = content_bytes.length ) == 0 ) {
			// 如果消息内容为空，则不进行传输
			return;
		}

		// 与服务器创建连接
		SocketChannel client = SocketChannel.open();
		client.connect( new InetSocketAddress( host, port ) );
		client.socket().setSoLinger( true, 3 );
		client.socket().setSoTimeout( 1000 );

		// =====================================================================
		int total_size = TYPE_SIZE + CONTENT_LEN_SIZE + TOKEN_SIZE + content_len;
		ByteBuffer buffer = ByteBuffer.allocate( total_size );

		ByteArrayOutputStream lenBytes = new ByteArrayOutputStream();
		// Type
		lenBytes.write( 1 & 0xFF );
		// 文件的长度
		lenBytes.write( ( content_len >> 16 ) & 0xFF );
		lenBytes.write( ( content_len >> 8 ) & 0xFF );
		lenBytes.write( content_len & 0xFF );
		// 写入长度数据
		buffer.put( lenBytes.toByteArray() );
		// 写入userToken数据
		buffer.put( userToken.getBytes( "UTF-8" ) );
		// 写入文件数据
		buffer.put( content_bytes );
		// =====================================================================

		// 反转缓冲区的标志，准备写
		buffer.flip();
		// 一直写，知道没有空余的数据
		while ( buffer.hasRemaining() ) {
			client.write( buffer );
		}

		// 关闭输出通道
		client.socket().shutdownOutput();

		// 处理响应
		final int reps_size = 1024;
		ByteBuffer resp_size_buffer = ByteBuffer.allocate( 2 );
		ByteBuffer resp_buffer = ByteBuffer.allocate( reps_size );
		ByteBuffer[] respBuffers = new ByteBuffer[] { resp_size_buffer, resp_buffer };

		// resp_size_buffer读满为止
		while ( resp_size_buffer.hasRemaining() ) {
			client.read( respBuffers );
		}

		// 计算出响应的长度
		int xmlLen = Utils.toInt( resp_size_buffer.array() );

		// TODO 处理响应内容
		ByteBuffer respXmlBuffer = ByteBuffer.allocate( xmlLen );
		client.read( respXmlBuffer );

		System.out.println( new String( respXmlBuffer.array() ) );
	}
}
